package org.easy.redis;


import com.alibaba.fastjson2.JSON;
import lombok.Getter;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author: Li chaojie
 * @Date: 2022/10/26
 * @Description:
 */
@Getter
public class CommonRedisClient {

    public CommonRedisClient(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    private final RedisTemplate<String, Object> redisTemplate;


    public void delete(String key) {
        redisTemplate.delete(key);
    }


    public void expire(String key, long timeout) {
        redisTemplate.expire(key, timeout, TimeUnit.MILLISECONDS);
    }

    public Boolean hasKey(String key) {
        return redisTemplate.hasKey(key);
    }


    //////////////////////////////  string //////////////////////////
    public String stringGet(String k) {
        Object o = redisTemplate.opsForValue().get(k);
        if (o == null) return null;
        return String.valueOf(o);
    }

    public <T> T stringGet(String k, Class<T> clazz) {
        Object o = redisTemplate.opsForValue().get(k);
        if (o == null) return null;
        return copy((String) o, clazz);
    }

    public Long stringGetLong(String k) {
        Object str = redisTemplate.opsForValue().get(k);
        if (null == str) {
            return null;
        } else {
            return Long.valueOf(String.valueOf(str));
        }
    }

    public Integer stringGetInteger(String k) {
        Object str = redisTemplate.opsForValue().get(k);
        if (null == str) {
            return null;
        } else {
            return Integer.valueOf(String.valueOf(str));
        }
    }

    public <V> void stringSet(String k, String v) {
        redisTemplate.opsForValue().set(k, v);
    }

    public <V> void stringSet(String k, V v) {
        redisTemplate.opsForValue().set(k, JSON.toJSONString(v));
    }

    public <V> void stringSet(String k, V v, long timeout) {
        redisTemplate.opsForValue().set(k, JSON.toJSONString(v), timeout, TimeUnit.MILLISECONDS);
    }

    public <V> void stringSet(String k, String v, long timeout) {
        redisTemplate.opsForValue().set(k, v, timeout, TimeUnit.MILLISECONDS);
    }

    public <V> Long stringIncrement(String k, long v) {
        return redisTemplate.opsForValue().increment(k, v);
    }

    public <V> Long stringIncrement(String k, int v) {
        return redisTemplate.opsForValue().increment(k, v);
    }

    //////////////////////////////  hash //////////////////////////
    public <HV> HV hashGet(String k, String hk) {
        return redisTemplate.<String, HV>opsForHash().get(k, hk);
    }

    public <HV> void hashPut(String k, String hk, HV hv) {
        redisTemplate.<String, HV>opsForHash().put(k, hk, hv);
    }

    public <HV> void hashPutAll(String k, Map<String, HV> map) {
        redisTemplate.<String, HV>opsForHash().putAll(k, map);
    }

    public void hashDelete(String k, String hk) {
        redisTemplate.opsForHash().delete(k, hk);
    }

    public void hashHas(String k, String hk) {
        redisTemplate.opsForHash().hasKey(k, hk);
    }

    public <HV> boolean hashPutIfAbsent(String k, String hk, HV hv) {
        return redisTemplate.opsForHash().putIfAbsent(k, hk, hv);
    }

    //////////////////////////////  zset //////////////////////////


    private <T> T copy(Object source, Class<T> target) {
        if (source == null || target == null) {
            return null;
        }
        return JSON.parseObject(JSON.toJSONString(source), target);
    }

    private <T> T copy(String source, Class<T> target) {
        if (source == null || target == null) {
            return null;
        }
        return JSON.parseObject(source, target);
    }

    private <T, E> List<T> copyList(List<E> source, Class<T> target) {
        if (source == null || target == null) {
            return new ArrayList<>();
        }

        return source.stream().map(e -> this.copy(e, target)).collect(Collectors.toList());
    }


}
